package com.njupt.simulation.utils;

import net.sf.geographiclib.Geodesic;
import net.sf.geographiclib.GeodesicData;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 本类用于演示如何在指定区域内生成随机地理坐标。
 */
public class RandomlyDemo {

    /**
     * 生成位于指定区域内的随机点列表。
     *
     * @param centerLat 中心点的纬度。
     * @param centerLon 中心点的经度。
     * @param radiusKm 区域半径（以千米为单位）。
     * @param density 密度，表示每平方千米内点的数量。
     * @return 返回一个列表，其中包含每个点的纬度和经度。
     */
    public static List<double[]> generateRandomPoints(double centerLat, double centerLon, double radiusKm, double density) {
        double radius = radiusKm * 1000; // 将半径从千米转换为米
        double area = Math.PI * Math.pow(radiusKm, 2); // 计算圆形区域的面积
        int numPoints = (int) (area * density); // 根据区域面积和密度计算随机点总数

        List<double[]> points = new ArrayList<>();
        Random random = new Random();

        // 循环生成每个随机点
        for (int i = 0; i < numPoints; i++) {
            // 生成随机距离和角度来计算随机点的位置
            double distance = radius * Math.sqrt(random.nextDouble());
            double angle = random.nextDouble() * 2 * Math.PI;

            // 调用方法计算随机点的坐标
            double[] point = calculateRandomPoint(centerLat, centerLon, distance, angle);
            points.add(point);
        }

        return points;

    }

    /**
     * 根据中心点、距离和角度计算随机点的坐标。
     *
     * @param centerLat 中心点的纬度。
     * @param centerLon 中心点的经度。
     * @param distance 与中心点的距离（以米为单位）。
     * @param angle 与正北方向的角度（以弧度为单位）。
     * @return 返回一个数组，其中包含计算出的随机点的纬度和经度。
     */
    private static double[] calculateRandomPoint(double centerLat, double centerLon, double distance, double angle) {

        // 使用GeographicLib库计算新的经纬度坐标
        GeodesicData gd = Geodesic.WGS84.Direct(centerLat, centerLon, Math.toDegrees(angle), distance);
        return new double[]{gd.lat2, gd.lon2};
    }

    /**
     * 主函数，用于测试生成随机点的方法。
     */
    public static void main(String[] args) {
        double centerLat = 28.3;
        double centerLon = 117;
        double radiusKm = 50;
        double density = 100;

        // 调用方法生成随机点列表
        List<double[]> points = generateRandomPoints(centerLat, centerLon, radiusKm, density);

        // 输出每个随机点的坐标
        for (int i = 0; i < points.size(); i++) {
            System.out.printf("No%d, Latitude = %.6f, Longitude = %.6f%n", i + 1, points.get(i)[0], points.get(i)[1]);
        }
    }
}
